﻿#ifndef _REC_READ_BASE_H_
#define _REC_READ_BASE_H_

#include<stdint.h>
#include<mutex>
#include "frame_shmem.h"
#include "imghost_api.h"
#include <thread>
using namespace std;

typedef enum _replay_seek_ret_
{
	SEEK_RET_OK = 0,		//成功

	SEEK_RET_BEGIN,			//之前
	SEEK_RET_END,			//之后

	SEEK_RET_FAILED=-1,		//失败, [文件本身有问题]
}REPLAY_SEEK_RET;

class CRecReadBase
{
public:
	CRecReadBase(int buf_size,int clientID,int channel);
	CRecReadBase();
	~CRecReadBase();

    virtual	int Open(const char * file_path,int64_t startTime = 0, int64_t endTime = 0,bool bClearBuf = false) = 0;
	int StartRead();

	void Close(bool bImmediate =false);
	void Clear();
	//读取数据到缓存中
	int  Read_TO_FIFO(int cache_wather = 50);

	virtual int SeekToTime(int64_t time,bool bClear = true) = 0;
	virtual int ReadFrame(unsigned char* buf, uint32_t bufLen) = 0;
	int  SetPalyMode(int mode, int speed, bool bReSeek);

protected:
	virtual int ReadFIFONormal() = 0;
	virtual int ReadFIFO2Forward() = 0;
	virtual int ReadFIFOForward() = 0;
	virtual int ReadFIFOReback() = 0;
	virtual bool IsOpen() = 0;
	int Read_proc();
	//由于存储在文件当中的音频是针对ASF文件编码的格式，但是在网络传输的需要使用RTP的方式
public:

	int GetFileIndex()
	{
		return m_fileIdx;
	}

	void SetBufSize(uint32_t bufSize)
	{
		m_nBufSize = bufSize;
	}

	uint32_t GetBufSize()
	{
		return m_nBufSize;
	}

	bool IsEffectTime(int64_t curTime)
	{
		if(curTime >= m_startTime && curTime < m_endTime)
		{
			return true;
		}
		return false;
	}

	int GetChannel()
	{
		return m_channel;
	}
	int GetIndexNum()
	{
		return m_maxIndex;
	}

	int64_t GetStartTime()
	{
		return m_firstTime;
	}

	int64_t GetEndTime()
	{
		if(m_playMode == REPLAY_REBACK)
		{
			return m_startTime - 10;
		}
		else
		{
			return m_endTime + 10;
		}
	}

	bool IsReadEnd()
	{
	  	return m_bDataEnd;
	}

	void ClearFIFOBuf()
	{
		if(m_pFIFO)
		{
			m_modeLock.lock();
			m_pFIFO->reset();
			m_modeLock.unlock();
		}
	}

	void DestroyFIFOBuf()
	{
		if(m_pFIFO)
		{
			m_modeLock.lock();
#ifndef _WIN32
            m_pFIFO->Close();
#endif
			m_modeLock.unlock();
		}
	}

	void RegisterClientInfo(int clientID, int ch)
	{
		m_clientID= clientID;
		m_channel = ch;
	}

	int  GetDataSize()
	{
		if( NULL == m_pFIFO)
		{
			return 0;
		}
		return m_pFIFO->GetDataSize();
	}
	int GetFileSize()
	{
		return m_fileLen;
	}
	int64_t GetLastPalyTime()//获取最后一回放帧的时间
	{
		return m_lastReadTime;
	}
protected:
	void StartDataIO();
	int  InitFIFOBuf(bool bClearBuf = true);
protected:
	bool     m_bComFile;			    //是否为通用文件
	uint32_t m_version;					//录像文件版本
	uint32_t m_fileLen;					//文件大小

	uint32_t m_fileIdx;					//文件块编号
	int		 m_segIdx;					//录像段编号
	uint32_t m_channel;					//文件所属通道
	int	     m_clientID;				//客户ID
	int64_t  m_firstTime;				//第一帧的时间
	int64_t  m_startTime;				//开始时间
	int64_t  m_endTime;					//结束时间
	int64_t  m_curTime;					//当前读取帧的时间
	int64_t  m_lastTime;				//上一帧视频的时间

	int64_t  m_lastReadTime;	        //最一帧被读取的帧时间

	bool	 m_bDataEnd;				//是否已经读取完成所有的数据
	uint32_t m_headOffset;			    //通用信息地址
	uint32_t m_recOffset;				//多录像段的信息
	uint32_t m_idxOffset;				//索引的偏移
	uint32_t m_dataOffset;				//数据区的偏移

	uint16_t m_fileStatus;				//文件是否正在写入
	uint16_t m_maxIndex;				//所有索引
	uint16_t m_gpsNum;					//所有GPS信息数量
	//索引信息区
	//STFS_REC_IDX *m_pIdxBuf;			//指向缓冲区首地址
	uint32_t      m_gpsBufSz;			//gps信息大小
	uint32_t	  m_curPos;				//读取数据的游标，指出当前文件指针的位置
	int			  m_curIndex;			//当前索引序号(SeekToTime时需要重新定位相应视频关键帧前的音频)

	int			  m_stepIFrame;			//I帧跳的间隔
	int           m_playMode;			//回放模式
	int			  m_speed;				//回放速度
	int			  m_noReadCount;		//循环去读的次数
	uint32_t	  m_nBufSize;			//读取缓冲大小
	mutex         m_modeLock;			//模式锁
	bool          m_bDownload;			//远程下载
	bool          m_bLocalBackup;		//本地备份
	bool          m_bSeek;				//t
	uint64_t      m_fileStartLBA;       //
	uint32_t       m_lastfrmNo;			//上一帧的编号
	//缓存
	CFrame_sharemem* m_pFIFO;           
	unsigned char * m_headBuf;			//头信息缓冲
	CFrmUtility     m_frmTool;			//帧头解析工具
	unsigned char*  m_frm_buf;          //单帧视频缓存 
	uint32_t        m_buf_size;         //缓存大小
	bool            m_bRawDev;			//是否裸磁盘设备
	thread         m_work_thd;          //读取视频工作线程
	bool           m_bStart = false; 
};
const  uint32_t	 HEAD_BUF_SIZE = 4096;		//头信息缓冲
#endif //_REC_READ_BASE_H_
